package com.tyc.transcation;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 类描述
 *
 * @author tyc
 * @version 1.0
 * @date 2021-11-05 10:56:17
 */
@Service
public class UserService {
    @Autowired
    JdbcTemplate jdbcTemplate;
    @Autowired
    UserService2 userService2;

    /**
     * 默认事务传播REQUIRED(没有则创建，有则加入，也就是一个事务)
     * 测试REQUIRED
     * 任何一个方法发生异常 都回滚
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public void updateUserMoney1(){
        jdbcTemplate.update("update user set money = ? where name = ?", 1, "zhangsan");
        try {
            userService2.updateUserMoney();
        } catch (Exception e) {
            e.printStackTrace();
        }
//        int i = 1/0;
    }

    /**
     * REQUIRED_NEW(新建一个事务)
     * 内部会滚不会引起外部会滚
     * 外部会滚也不会引起内部会滚
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public void updateUserMoney2(){
        jdbcTemplate.update("update user set money = ? where name = ?", 1, "zhangsan");
        try {
            // 注意给查询条件的字段加唯一索引，防止表锁导致下面这个sql无法执行
            userService2.updateUserMoney2();
        } catch (Exception e) {
            e.printStackTrace();
        }
        int i = 1/0;
    }

    /**
     * NESTED(外部无事务与REQUIRED一样，有则开启嵌套事务)
     * 内部回滚不会引起外部会滚
     * 外部回滚会引起内部会滚
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public void updateUserMoney3(){
        jdbcTemplate.update("update user set money = ? where name = ?", 1, "zhangsan");
        try {
            userService2.updateUserMoney3();
        } catch (Exception e) {
            e.printStackTrace();
        }
        int i = 1/0;
    }

    /**
     * MANDATORY必须以事务方式运行，(一个事务) 否则报错
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public void updateUserMoney4(){
        jdbcTemplate.update("update user set money = ? where name = ?", 1, "zhangsan");
        try {
            userService2.updateUserMoney4();
        } catch (Exception e) {
            e.printStackTrace();
        }
        int i = 1/0;
    }

    /**
     * NEVER禁止以事务方式运行 否则报错
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public void updateUserMoney5(){
        jdbcTemplate.update("update user set money = ? where name = ?", 1, "zhangsan");
        try {
            userService2.updateUserMoney5();
        } catch (Exception e) {
            e.printStackTrace();
        }
//        int i = 1/0;
    }

    /**
     * SUPPORTS 有事务在这个事务中运行 没有则以非事务方式运行
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public void updateUserMoney6(){
        jdbcTemplate.update("update user set money = ? where name = ?", 1, "zhangsan");
        try {
            userService2.updateUserMoney6();
        } catch (Exception e) {
            e.printStackTrace();
        }
//        int i = 1/0;
    }

    /**
     * NOT_SUPPORTED 不在事务中运行 有则将其挂起
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public void updateUserMoney7(){
        jdbcTemplate.update("update user set money = ? where name = ?", 1, "zhangsan");
        try {
            userService2.updateUserMoney7();
        } catch (Exception e) {
            e.printStackTrace();
        }
//        int i = 1/0;
    }

    /**
     * 只读事务 不允许执行修改操作
     * 使用：
     *      查询报表，需要多次查询，防止结果不一致
     */
    @Transactional(readOnly = true)
    public void getUserByMoney(){
        jdbcTemplate.execute("select * from user where money = 1");
        try {
            userService2.getUserByMoney();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 事务失效如下：
     * 普通方法和事务方法之间的嵌套调用(因为需要根据注解来代理)
     * 异常被try
     * 异常类型与触发回滚类型不一致
     */

}
